//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.TridentWordAddIn.ResourceHelper;

namespace Microsoft.TridentWordAddIn.Presentation
{
    /// <summary>
    /// Class representing the form which displays messages (ex: exceptions)
    /// </summary>
    internal partial class MessageForm : BaseForm
    {
        private bool isExpanded;
        private int detailPanelHeight;

        /// <summary>
        /// Initializes a new instance of the <see cref="MessageForm"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="details">The details.</param>
        private MessageForm(string message, string details)
        {
            this.InitializeForm();
            this.txtMessage.Text = message;
            this.btnDetails.Visible = true;
            this.txtDetail.Text = details;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MessageForm"/> class.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="showOnlyMessage">if set to <c>true</c> [show only message].</param>
        private MessageForm(Exception ex, bool showOnlyMessage)
        {
            this.InitializeForm();
            this.txtMessage.Text = ex.Message;

            if (showOnlyMessage)
            {
                this.btnDetails.Visible = false;
            }
            else
            {
                StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
                this.WriteException(ex, writer);
                this.txtDetail.Text = writer.GetStringBuilder().ToString();
            }

            this.WriteExceptionToTrace(ex);
        }

        /// <summary>
        /// Shows the unhandled exception message.
        /// </summary>
        /// <param name="ex">The exception.</param>
        public static void ShowUnhandledExceptionMessage(Exception ex)
        {
            ShowUnhandledExceptionMessage(ex, true);
        }

        /// <summary>
        /// Shows the unhandled exception message.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <param name="messageOnly">if set to <c>true</c> show only the message.</param>
        public static void ShowUnhandledExceptionMessage(Exception ex, bool messageOnly)
        {
            using (MessageForm form = new MessageForm(ex, messageOnly))
            {
                form.ShowDialog();
            }
        }

        /// <summary>
        /// Shows the unhandled exception message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="details">The details.</param>
        public static void ShowUnhandledExceptionMessage(string message, string details)
        {
            using (MessageForm form = new MessageForm(message, details))
            {
                form.ShowDialog();
            }
        }

        /// <summary>
        /// Initializes the form.
        /// </summary>
        private void InitializeForm()
        {
            this.InitializeComponent();
            this.CollapseDetails();
        }

        /// <summary>
        /// Collapses the details.
        /// </summary>
        private void CollapseDetails()
        {
            this.detailPanelHeight = this.pnlDetails.Height;
            int newHeight = this.Height - this.detailPanelHeight;
            this.Height = newHeight > 0 ? newHeight : 0;
        }

        /// <summary>
        /// Expands the details.
        /// </summary>
        private void ExpandDetails()
        {
            this.pnlDetails.Height = this.detailPanelHeight;
            this.Height = this.Height + this.detailPanelHeight;
        }

        /// <summary>
        /// Writes the exception to trace.
        /// </summary>
        /// <param name="ex">The ex.</param>
        private void WriteExceptionToTrace(Exception ex)
        {
            if (ex == null)
            {
                return;
            }

            this.WriteExceptionToTrace(ex.InnerException);
            Trace.WriteLine(ex.ToString(), TraceLevel.Error.ToString());
        }

        /// <summary>
        /// Writes the exception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="writer">The writer.</param>
        private void WriteException(Exception ex, TextWriter writer)
        {
            if (ex == null || writer == null)
            {
                return;
            }

            this.WriteException(ex.InnerException, writer);
            writer.WriteLine(ex);
        }

        /// <summary>
        /// Handles the Click event of the DetailsButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void DetailsButton_Click(object sender, EventArgs e)
        {
            if (this.isExpanded)
            {
                this.isExpanded = false;
                this.CollapseDetails();
                this.btnDetails.Text = ResourceFetcher.GetString("ShowDetails");
            }
            else
            {
                this.isExpanded = true;
                this.ExpandDetails();
                this.btnDetails.Text = ResourceFetcher.GetString("HideDetails");
            }

            this.txtMessage.Invalidate();
        }
    }
}